Protractor Configuration And Integration With CucumberJS

Introduction 

 
In the previous article, I spoke about the cucumberjs basics. In this article, we will be talking about integrating protractor with cucumber. If you have not visited my previous article, I ask you to click on this link.
 

Configuring Protractor

 
If you have not installed the protractor in your machine, I would recommend you to visit this website (https://www.protractortest.org/#/). This contains all the info on setting up the protractor. In this article, I am using the VScode editor; however, you can use any editor.
 
Go to VScode editor -> Terminal-> New Terminal
 
Inside the terminal, please execute the below commands. All the steps are mentioned on the protractor website.
  1. npm install -g protractor   
  2. webdriver-manager update  
  3. webdriver-manager start   
After executing the above commands, we need to check whether protractor is working fine or not. To check that, please consider the below example.
 
Create a ".js" file in the project and add the below code (Ex: protractorTest.js)
  1. describe('angularjs homepage todo list', function() {  
  2.     it('should add a todo', function() {  
  3.       browser.get('https://angularjs.org');  
  4.     
  5.       element(by.model('todoList.todoText')).sendKeys('write first protractor test');  
  6.       element(by.css('[value="add"]')).click();  
  7.     
  8.       var todoList = element.all(by.repeater('todo in todoList.todos'));  
  9.       expect(todoList.count()).toEqual(3);  
  10.       expect(todoList.get(2).getText()).toEqual('write first protractor test');  
  11.     
  12.       // You wrote your first test, cross it off the list  
  13.       todoList.get(2).element(by.css('input')).click();  
  14.       var completedAmount = element.all(by.css('.done-true'));  
  15.       expect(completedAmount.count()).toEqual(2);  
  16.     });  
  17.   });  
In order to execute the above code, you need to specify the conf.js file which contains browser and specs details, as shown below.
 
In the below example, I have given the "directConnect". We use this command in order to directly execute in the browser without starting the "webdriver -manager". This applies only to Chrome and Firefox. The rest of the browsers "directconnect" will not work 
  1. exports.config = {  
  2.     //seleniumAddress: 'http://localhost:4444/wd/hub',  
  3.   
  4.     directConnect: true,  
  5.     specs: ['protractorTest.js']  
  6.   };  
Now in the Terminal, execute the command mentioned below. Your specs should run successfully.
  1. protractor conf.js  
After executing the above code successfully, our protractor is working fine. Now, to integrate it with cucumberjs, you need to execute the below command in the terminal. 
  1. npm install protractor-cucumber-framework --save-dev  
After installing the above command, you can check in your package.config file. Once this installation is done, you can create your first feature file, as shown below.
  1. Feature: Login    
  2.     In order to login to the application    
  3.     As a User    
  4.     I need to enter the Valid username and Password    
  5.     
  6.     Scenario: In order to login to the angular app    
  7.         Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login"   
  8.         When user login with "angular" and "password"  
  9.         And User enters the Admin "TestUser"  
  10.         Then user should login succcessfully   
 The above is the simple feature file which runs only for one test case. You can execute it using below command. I have given the feature file name as "Login".
  1. .\node_modules\.bin\cucumber-js .\features\Login.feature   
  It will provide you the step definition in the terminal, as shown below.
  1. 1) Scenario: In order to login to the angular app # features\Login.feature:6  
  2.    √ Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login" # features\stepDefinition\LoginDefinition.js:4  
  3.    √ When user login with "angular" and "password" # features\stepDefinition\LoginDefinition.js:10  
  4.    ? And User enters the Admin "UserNames"  
  5.        Undefined. Implement with the following snippet:  
  6.   
  7.          When('User enters the Admin {string}', function (string) {  
  8.            // Write code here that turns the phrase above into concrete actions  
  9.            return 'pending';  
  10.          });  
  11.   
  12.    ? Then user should login succcessfully  
  13.        Undefined. Implement with the following snippet:  
  14.   
  15.          Then('user should login succcessfully', function () {  
  16.            // Write code here that turns the phrase above into concrete actions  
  17.            return 'pending';  
  18.          });  
You can copy the step definition and implement the same in your "stepdefinition.js" file.
  1. var {Given, When, Then, Before} = require('cucumber');    
  2. const { browser, element } = require('protractor');  
  3.   
  4.   
  5. Before({timeout: 60 * 1000}, function() {  
  6.   // Does some slow browser/filesystem/network actions  
  7.   browser.manage().window().maximize();  
  8. });  
  9.   
  10. Given(/^open the application "([^"]*)"$/, function (string) {  
  11.     return  browser.get(string);  
  12. });  
  13.   
  14. When('user login with {string} and {string}', function (string, string2) {  
  15.   // Write code here that turns the phrase above into concrete actions  
  16.   element(by.model('Auth.user.name')).sendKeys(string);  
  17.   element(by.model('Auth.user.password')).sendKeys(string2);  
  18.   return console.log("entered the user name and password");  
  19. });  
  20.   
  21. When('User enters the Admin {string}', function (string) {  
  22.   // Write code here that turns the phrase above into concrete actions  
  23.   element(by.model('model[options.key]')).sendKeys(string);  
  24.   return console.log("enetered the logged in user name");  
  25.     
  26. });  
  27. Then('user should login succcessfully', function () {  
  28.   // Write code here that turns the phrase above into concrete actions  
  29.   return console.log("success");  
  30. });  
Now once the "Logindefinition.js" file is implemented, you need to integrate it with protractor. For that, you need to do some modifications in the "conf.js" files. Create a "protractor.conf.js" file in the project and add the below code.
 
You can use "directConnect" to directly open the application. You need to add "framework and frameworkPath", In the specs section you need to add the feature file name, and "cucumberOpts" section you can add the step definition file names related to the ".feature" file. If you do not have any tags keep that as "false" as of now. 
 
If you do not know what is "tags" in cucumber, you can refer here.
  1. exports.config = {  
  2.     //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',  
  3.     directConnect:true,  
  4.     getPageTimeout: 60000,  
  5.     allScriptsTimeout: 500000,  
  6.     framework: 'custom',  
  7.     // path relative to the current config file  
  8.     frameworkPath: require.resolve('protractor-cucumber-framework'),  
  9.     capabilities: {  
  10.       'browserName''chrome'  
  11.     },  
  12.       
  13.     // Spec patterns are relative to this directory.  
  14.     specs: [  
  15.       'features/*.feature'  
  16.     ],  
  17.   
  18.     cucumberOpts: {  
  19.       require: 'features/stepDefinition/LoginDefinition.js',  
  20.       tags: false,  
  21.         
  22.     }  
  23.   
  24. };  

Multiple Test Data and Multiple Scenarios

 
In the above example, I have created only one scenario which runs for only one test case. In this example, I will explain how to create multiple scenarios with dynamic test data execution. 
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Background:  
  7.         Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login"  
  8.   
  9.     Scenario Outline: Verify the title of the page  
  10.         Then the title of page is
  11.   
  12.     Scenario Outline: In order to login to the angular app  
  13.         When user login with "<username>" and "<password>"  
  14.         And User enters the Admin "<username1>"  
  15.         Then user should login succcessfully  
  16.         Then user should logout succcessfully  
  17.   
  18.   
  19.   
  20.         Examples:  
  21.             | username | password | username1 | 
  22.             | angular  | password | user1     |   
  23.             | angular  | password | user2     | 
  24.          
Step definition code
  1. var {Given, When, Then, Before, After} = require('cucumber');    
  2. const { browser, element } = require('protractor');  
  3.   
  4.   
  5. Before({timeout: 60 * 1000}, function() {  
  6.   // Does some slow browser/filesystem/network actions  
  7.   browser.manage().window().maximize();  
  8. });  
  9.   
  10.   
  11.   
  12. Given("open the application {string}", function (string) {  
  13.     return  browser.get(string);  
  14. });  
  15.   
  16. Then("the title of the page is", function () {  
  17.   // Write code here that turns the phrase above into concrete actions  
  18.   browser.sleep(4000);  
  19.   var titleofPage = browser.getTitle();  
  20.   titleofPage.then(function(text){  
  21.     console.log("page title is : "+ text);  
  22.   });  
  23. });  
  24.   
  25. When("user login with {string} and {string}", function (string, string2) {  
  26.   // Write code here that turns the phrase above into concrete actions  
  27.   element(by.model('Auth.user.name')).sendKeys(string);  
  28.   element(by.model('Auth.user.password')).sendKeys(string2);  
  29.   return console.log("entered the user name and password");  
  30. });  
  31.   
  32. When("User enters the Admin {string}", async function (string) {  
  33.   // Write code here that turns the phrase above into concrete actions  
  34.   await element(by.model('model[options.key]')).sendKeys(string);  
  35.   return console.log("enetered the logged in user name");  
  36.     
  37. });  
  38. Then("user should login succcessfully", function () {  
  39.   // Write code here that turns the phrase above into concrete actions  
  40.   element(by.buttonText("Login")).click();  
  41.   return console.log("user logged in successfully");  
  42. });  
  43. Then("user should logout succcessfully", function () {  
  44.   // Write code here that turns the phrase above into concrete actions  
  45.   browser.sleep(4000);  
  46.   return element(by.linkText("Logout")).click();  
  47. });  

Executing the Scenarios with Tags

 
In the above example, we saw how to run multiple scenarios. While testing, there will be some test cases we need to keep for smoke testing, integration testing, functional testing. So cucumber, as provided the tags, which help us to execute the particular test case with the help of tags. Let's see how we can do it, by taking the above example.
 
So in the below feature file, mark one scenario with the tag "@smoke"
  1. Feature: Login  
  2.     In order to login to the application  
  3.     As a User  
  4.     I need to enter the Valid username and Password  
  5.   
  6.     Background:  
  7.         Given open the application "http://www.way2automation.com/angularjs-protractor/registeration/#/login"  
  8.   
  9.     Scenario: Verify the title of the page  
  10.         Then the title of the page is  
  11.   
  12.     @smoke  
  13.     Scenario Outline: In order to login to the angular app  
  14.         When user login with "<username>" and "<password>"  
  15.         And User enters the Admin "<username1>"  
  16.         Then user should login succcessfully  
  17.         Then user should logout succcessfully  
  18.   
  19.   
  20.   
  21.         Examples:  
  22.             | username | password | username1 |  
  23.             | angular  | password | user1     |  
  24.             | angular  | password | user1     |  
  25.          
In the conf.js file, you need to add the tag.
  1.   exports.config = {  
  2.     //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',  
  3.     directConnect:true,  
  4.     getPageTimeout: 60000,  
  5.     allScriptsTimeout: 500000,  
  6.     framework: 'custom',  
  7.     // path relative to the current config file  
  8.     frameworkPath: require.resolve('protractor-cucumber-framework'),  
  9.     capabilities: {  
  10.       'browserName''chrome'  
  11.     },  
  12.       
  13.     // Spec patterns are relative to this directory.  
  14.     specs: [  
  15.       'features/*.feature'  
  16.     ],  
  17.   
  18.     cucumberOpts: {  
  19.       tags: ['@smoke'],  
  20.       require: 'features/stepDefinition/LoginDefinition.js',  
  21.       format:'json:cucumber_report.json'  
  22.         
  23.     }  
  24.   
  25.      
  26. };  
So when you execute the tag with '@smoke' gets executed.
 
You can see in the below console. only 2 scenarios are executed w.rt to test data passed.
 
 

Generating HTML Reports

 
Let's see how to generate reports for the above script. In order to generate the report, we need to first create "cucumber_report.json" file. Please add the line of code in conf.js under "cucumberOpts"
  1. exports.config = {  
  2.     //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',  
  3.     directConnect:true,  
  4.     getPageTimeout: 60000,  
  5.     allScriptsTimeout: 500000,  
  6.     framework: 'custom',  
  7.     // path relative to the current config file  
  8.     frameworkPath: require.resolve('protractor-cucumber-framework'),  
  9.     capabilities: {  
  10.       'browserName''chrome'  
  11.     },  
  12.       
  13.     // Spec patterns are relative to this directory.  
  14.     specs: [  
  15.       'features/*.feature'  
  16.     ],  
  17.   
  18.     cucumberOpts: {  
  19.       require: 'features/stepDefinition/LoginDefinition.js',  
  20.       format:'json:cucumber_report.json',  
  21.       tags: false,  
  22.         
  23.     }  
  24.   
  25.      
  26. };  
After executing the above code with command "protractor <name of conf file>.js". The "cucumber_report.json" file will be generated. The next step is to create "index.js file.
  1. var reporter = require('cucumber-html-reporter');    
  2.      
  3. var options = {    
  4.         theme: 'bootstrap',    
  5.         jsonFile: './cucumber_report.json',    
  6.         output: './cucumber_report.html',    
  7.         reportSuiteAsScenarios: true,    
  8.         scenarioTimestamp: true,    
  9.         launchReport: true,    
  10.         metadata: {    
  11.             "App Version":"0.3.2",    
  12.             "Test Environment""STAGING",    
  13.             "Browser""Chrome  54.0.2840.98",    
  14.             "Platform""Windows 10",    
  15.             "Parallel""Scenarios",    
  16.             "Executed""Remote"    
  17.         }    
  18.     };    
  19.      
  20.     reporter.generate(options);     
Execute the command "node index.js" in the terminal. It will redirect you to the reports.html file which opens up in the browser
 
 

Running parallel on Multiple Browsers

 
When you want to execute tests on multiple browsers at the same time parallelly. Then you need to user the Mutiple Capabilities, shown below:
  1. exports.config = {  
  2.     //seleniumAddress: 'http://127.0.0.1:4444/wd/hub',  
  3.     directConnect:true,  
  4.     getPageTimeout: 60000,  
  5.     allScriptsTimeout: 500000,  
  6.     framework: 'custom',  
  7.     // path relative to the current config file  
  8.     frameworkPath: require.resolve('protractor-cucumber-framework'),  
  9.     multiCapabilities:[{  
  10.       'browserName''chrome'  
  11.     },{  
  12.       'browserName''firefox'  
  13.     }],  
  14.       
  15.     // Spec patterns are relative to this directory.  
  16.     specs: [  
  17.       'features/*.feature'  
  18.     ],  
  19.   
  20.     maxSessions:1,  //One browser will open at a time.
  21.   
  22.     cucumberOpts: {  
  23.       tags: ['@smoke'],  
  24.       require: 'features/stepDefinition/LoginDefinition.js',  
  25.       format:'json:cucumber_report.json'  
  26.         
  27.     }  
  28.   
  29.      
  30. };  
That's it about cucumber, I have not mentioned the customization of conf.js and customization of cucumber reports in this article. That is because it's already available on the websites I mentioned. 
 
Thank You! Happy Coding :-)